#include "xmlrpcconnection.h"
#include "xmlrpcintrospect.h"
#include "xmlrpcrequest.h"
#include "xmlrpcresponse.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

namespace XmlRpc {

/*
 * TODO: Handle errors from the XmlRpcConnection
 */

XmlRpcIntrospect::XmlRpcIntrospect(QPointer<XmlRpcConnection> connection)
    : QObject(0), m_con(connection)
{
}

XmlRpcIntrospect::~XmlRpcIntrospect()
{
}

bool XmlRpcIntrospect::isValid() const
{
    return !m_con.isNull();
}

bool XmlRpcIntrospect::methodHelp(const QString &methodName)
{
    if (!isValid())
        return false;
    QList<QVariant> params;
    params << methodName;
    sendRequest("system.methodHelp", SLOT(receiveMethodHelp(XmlRpcResponse*)), params);
    return true;
}

bool XmlRpcIntrospect::listMethods()
{
    if (!isValid())
        return false;
    sendRequest("system.listMethods", SLOT(receiveMethodList(XmlRpcResponse*)), QList<QVariant>());
    return true;
}


bool XmlRpcIntrospect::methodSignature(const QString &methodName)
{
    if (!isValid())
        return false;
    QList<QVariant> params;
    params << methodName;
    sendRequest("system.methodSignature", SLOT(receiveMethodSignature(XmlRpcResponse*)), params);
    return true;
}

void XmlRpcIntrospect::receiveMethodHelp(XmlRpcResponse *response)
{
    QVariant result = response->returnValue();
    QString help;
    if (result.canConvert(QVariant::String))
        help = result.toString();
    emit methodHelpReceived(help);
    response->deleteLater();
}

void XmlRpcIntrospect::receiveMethodList(XmlRpcResponse *response)
{
    QVariant result = response->returnValue();
    if (result.canConvert(QVariant::StringList)) {
        QStringList methods(result.toStringList());
        emit methodListReceived(methods);
    }
    response->deleteLater();
}

void XmlRpcIntrospect::receiveMethodSignature(XmlRpcResponse *response)
{
    QVariant result = response->returnValue();
    emit methodSignatureReceived(result);
    response->deleteLater();
}

void XmlRpcIntrospect::sendRequest(const QString &method, const char *slot,
                                   const QList<QVariant> &params)
{
    XmlRpcRequest request(XmlRpcRequest::DoNotPropagate);
    request.setMethod(method);
    if (params.count() > 0)
        request.setParams(params);
    XmlRpcResponse *resp = m_con->query(request);
    connect(resp, SIGNAL(finished(XmlRpcResponse*)), this, slot);
}

} // namespace XmlRpc
